home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / extralev.c < prev    next >
C/C++ Source or Header  |  1992-11-29  |  9KB  |  343 lines

  1. /*    SCCS Id: @(#)extralev.c    3.1    92/05/27            */
  2. /*    Copyright 1988, 1989 by Ken Arromdee                */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef REINCARNATION
  8.  
  9. struct rogueroom {
  10.     xchar rlx, rly;
  11.     xchar dx, dy;
  12.     boolean real;
  13.     uchar doortable;
  14.     int nroom; /* Only meaningful for "real" rooms */
  15. };
  16. #define UP 1
  17. #define DOWN 2
  18. #define LEFT 4
  19. #define RIGHT 8
  20.  
  21. static struct rogueroom NEARDATA r[3][3];
  22. static void FDECL(roguejoin,(int,int,int,int,int));
  23. static void FDECL(roguecorr,(int,int,int));
  24. static void FDECL(miniwalk,(int,int));
  25.  
  26. static
  27. void
  28. roguejoin(x1,y1,x2,y2, horiz)
  29. int x1,y1,x2,y2;
  30. int horiz;
  31. {
  32.     register int x,y,middle;
  33. #ifndef MAX
  34. #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  35. #endif
  36. #ifndef MIN
  37. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  38. #endif
  39.     if (horiz) {
  40.         middle = x1 + rn2(x2-x1+1);
  41.         for(x=MIN(x1,middle); x<=MAX(x1,middle); x++)
  42.             corr(x, y1);
  43.         for(y=MIN(y1,y2); y<=MAX(y1,y2); y++)
  44.             corr(middle,y);
  45.         for(x=MIN(middle,x2); x<=MAX(middle,x2); x++)
  46.             corr(x, y2);
  47.     } else {
  48.         middle = y1 + rn2(y2-y1+1);
  49.         for(y=MIN(y1,middle); y<=MAX(y1,middle); y++)
  50.             corr(x1, y);
  51.         for(x=MIN(x1,x2); x<=MAX(x1,x2); x++)
  52.             corr(x, middle);
  53.         for(y=MIN(middle,y2); y<=MAX(middle,y2); y++)
  54.             corr(x2,y);
  55.     }
  56. }
  57.  
  58. static
  59. void
  60. roguecorr(x, y, dir)
  61. int x,y,dir;
  62. {
  63.     register int fromx, fromy, tox, toy;
  64.  
  65.     if (dir==DOWN) {
  66.         r[x][y].doortable &= ~DOWN;
  67.         if (!r[x][y].real) {
  68.             fromx = r[x][y].rlx; fromy = r[x][y].rly;
  69.             fromx += 1 + 26*x; fromy += 7*y;
  70.         } else {
  71.             fromx = r[x][y].rlx + rn2(r[x][y].dx);
  72.             fromy = r[x][y].rly + r[x][y].dy;
  73.             fromx += 1 + 26*x; fromy += 7*y;
  74.             if (!IS_WALL(levl[fromx][fromy].typ))
  75.                 impossible("down: no wall at %d,%d?",fromx,
  76.                                     fromy);
  77.             dodoor(fromx, fromy, &rooms[r[x][y].nroom]);
  78.             levl[fromx][fromy].doormask = D_NODOOR;
  79.             fromy++;
  80.         }
  81.         if(y >= 2) {
  82.             impossible("down door from %d,%d going nowhere?",x,y);
  83.             return;
  84.         }
  85.         y++;
  86.         r[x][y].doortable &= ~UP;
  87.         if (!r[x][y].real) {
  88.             tox = r[x][y].rlx; toy = r[x][y].rly;
  89.             tox += 1 + 26*x; toy += 7*y;
  90.         } else {
  91.             tox = r[x][y].rlx + rn2(r[x][y].dx);
  92.             toy = r[x][y].rly - 1;
  93.             tox += 1 + 26*x; toy += 7*y;
  94.             if (!IS_WALL(levl[tox][toy].typ))
  95.                 impossible("up: no wall at %d,%d?",tox,toy);
  96.             dodoor(tox, toy, &rooms[r[x][y].nroom]);
  97.             levl[tox][toy].doormask = D_NODOOR;
  98.             toy--;
  99.         }
  100.         roguejoin(fromx, fromy, tox, toy, FALSE);
  101.         return;
  102.     } else if (dir == RIGHT) {
  103.         r[x][y].doortable &= ~RIGHT;
  104.         if (!r[x][y].real) {
  105.             fromx = r[x][y].rlx; fromy = r[x][y].rly;
  106.             fromx += 1 + 26*x; fromy += 7*y;
  107.         } else {
  108.             fromx = r[x][y].rlx + r[x][y].dx;
  109.             fromy = r[x][y].rly + rn2(r[x][y].dy);
  110.             fromx += 1 + 26*x; fromy += 7*y;
  111.             if (!IS_WALL(levl[fromx][fromy].typ))
  112.                 impossible("down: no wall at %d,%d?",fromx,
  113.                                     fromy);
  114.             dodoor(fromx, fromy, &rooms[r[x][y].nroom]);
  115.             levl[fromx][fromy].doormask = D_NODOOR;
  116.             fromx++;
  117.         }
  118.         if(x >= 2) {
  119.             impossible("right door from %d,%d going nowhere?",x,y);
  120.             return;
  121.         }
  122.         x++;
  123.         r[x][y].doortable &= ~LEFT;
  124.         if (!r[x][y].real) {
  125.             tox = r[x][y].rlx; toy = r[x][y].rly;
  126.             tox += 1 + 26*x; toy += 7*y;
  127.         } else {
  128.             tox = r[x][y].rlx - 1;
  129.             toy = r[x][y].rly + rn2(r[x][y].dy);
  130.             tox += 1 + 26*x; toy += 7*y;
  131.             if (!IS_WALL(levl[tox][toy].typ))
  132.                 impossible("left: no wall at %d,%d?",tox,toy);
  133.             dodoor(tox, toy, &rooms[r[x][y].nroom]);
  134.             levl[tox][toy].doormask = D_NODOOR;
  135.             tox--;
  136.         }
  137.         roguejoin(fromx, fromy, tox, toy, TRUE);
  138.         return;
  139.     } else impossible("corridor in direction %d?",dir);
  140. }
  141.             
  142. /* Modified walkfrom() from mkmaze.c */
  143. static
  144. void
  145. miniwalk(x, y)
  146. int x,y;
  147. {
  148.     register int q, dir;
  149.     int dirs[4];
  150.  
  151.     while(1) {
  152.         q = 0;
  153. #define doorhere (r[x][y].doortable)
  154.         if (x>0 && (!(doorhere & LEFT)) &&
  155.                     (!r[x-1][y].doortable || !rn2(10)))
  156.             dirs[q++] = 0;
  157.         if (x<2 && (!(doorhere & RIGHT)) &&
  158.                     (!r[x+1][y].doortable || !rn2(10)))
  159.             dirs[q++] = 1;
  160.         if (y>0 && (!(doorhere & UP)) &&
  161.                     (!r[x][y-1].doortable || !rn2(10)))
  162.             dirs[q++] = 2;
  163.         if (y<2 && (!(doorhere & DOWN)) &&
  164.                     (!r[x][y+1].doortable || !rn2(10)))
  165.             dirs[q++] = 3;
  166.     /* Rogue levels aren't just 3 by 3 mazes; they have some extra
  167.      * connections, thus that 1/10 chance
  168.      */
  169.         if (!q) return;
  170.         dir = dirs[rn2(q)];
  171.         switch(dir) { /* Move in direction */
  172.             case 0: doorhere |= LEFT;
  173.                 x--;
  174.                 doorhere |= RIGHT;
  175.                 break;
  176.             case 1: doorhere |= RIGHT;
  177.                 x++;
  178.                 doorhere |= LEFT;
  179.                 break;
  180.             case 2: doorhere |= UP;
  181.                 y--;
  182.                 doorhere |= DOWN;
  183.                 break;
  184.             case 3: doorhere |= DOWN;
  185.                 y++;
  186.                 doorhere |= UP;
  187.                 break;
  188.         }
  189.         miniwalk(x,y);
  190.     }
  191. }
  192.  
  193. void
  194. makeroguerooms() {
  195.     register int x,y;
  196.     /* Rogue levels are structured 3 by 3, with each section containing
  197.      * a room or an intersection.  The minimum width is 2 each way.
  198.      * One difference between these and "real" Rogue levels: real Rogue
  199.      * uses 24 rows and NetHack only 23.  So we cheat a bit by making the
  200.      * second row of rooms not as deep.
  201.      *
  202.      * Each normal space has 6/7 rows and 25 columns in which a room may
  203.      * actually be placed.  Walls go from rows 0-5/6 and columns 0-24.
  204.      * Not counting walls, the room may go in
  205.      * rows 1-5 and columns 1-23 (numbering starting at 0).  A room
  206.      * coordinate of this type may be converted to a level coordinate
  207.      * by adding 1+28*x to the column, and 7*y to the row.  (The 1
  208.      * is because column 0 isn't used [we only use 1-78]).
  209.      * Room height may be 2-4 (2-5 on last row), length 2-23 (not
  210.      * counting walls)
  211.      */
  212. #define here r[x][y]
  213.  
  214.     nroom = 0;
  215.     for(y=0; y<3; y++) for(x=0; x<3; x++) {
  216.         /* Note: we want to insure at least 1 room.  So, if the
  217.          * first 8 are all dummies, force the last to be a room.
  218.          */
  219.         if (!rn2(5) && (nroom || (x<2 && y<2))) {
  220.             /* Arbitrary: dummy rooms may only go where real
  221.              * ones do.
  222.              */
  223.             here.real = FALSE;
  224.             here.rlx = rn1(22, 2);
  225.             here.rly = rn1((y==2)?4:3, 2);
  226.         } else {
  227.             here.real = TRUE;
  228.             here.dx = rn1(22, 2); /* 2-23 long, plus walls */
  229.             here.dy = rn1((y==2)?4:3, 2); /* 2-5 high, plus walls */
  230.  
  231.             /* boundaries of room floor */
  232.             here.rlx = rnd(23 - here.dx + 1);
  233.             here.rly = rnd(((y==2) ? 5 : 4)- here.dy + 1);
  234.             nroom++;
  235.         }
  236.         here.doortable = 0;
  237.     }
  238.     miniwalk(rn2(3), rn2(3));
  239.     nroom = 0;
  240.     for(y=0; y<3; y++) for(x=0; x<3; x++) {
  241.         if (here.real) { /* Make a room */
  242.             int lowx, lowy, hix, hiy;
  243.  
  244.             r[x][y].nroom = nroom;
  245.             smeq[nroom] = nroom;
  246.  
  247.             lowx = 1 + 26*x + here.rlx;
  248.             lowy = 7*y + here.rly;
  249.             hix = 1 + 26*x + here.rlx + here.dx - 1;
  250.             hiy = 7*y + here.rly + here.dy - 1;
  251.             /* Strictly speaking, it should be lit only if above
  252.              * level 10, but since Rogue rooms are only
  253.              * encountered below level 10, use !rn2(7).
  254.              */
  255.  
  256.             add_room(lowx, lowy, hix, hiy, !rn2(7), OROOM, FALSE);
  257.         }
  258.     }
  259.  
  260.     /* Now, add connecting corridors. */
  261.     for(y=0; y<3; y++) for(x=0; x<3; x++) {
  262.         if (here.doortable & DOWN)
  263.             roguecorr(x, y, DOWN);
  264.         if (here.doortable & RIGHT)
  265.             roguecorr(x, y, RIGHT);
  266.         if (here.doortable & LEFT)
  267.             impossible ("left end of %d, %d never connected?",x,y);
  268.         if (here.doortable & UP)
  269.             impossible ("up end of %d, %d never connected?",x,y);
  270.     }
  271. }
  272.  
  273. void
  274. corr(x,y)
  275. int x, y;
  276. {
  277.     if (rn2(50)) {
  278.         levl[x][y].typ = CORR;
  279.     } else {
  280.         levl[x][y].typ = SCORR;
  281.     }
  282. }
  283.  
  284. void
  285. makerogueghost()
  286. {
  287.     register struct monst *ghost;
  288.     struct obj *ghostobj;
  289.     struct mkroom *croom;
  290.     int x,y;
  291.  
  292.     if (!nroom) return; /* Should never happen */
  293.     croom = &rooms[rn2(nroom)];
  294.     x = somex(croom); y = somey(croom);
  295.     if (!(ghost = makemon(&mons[PM_GHOST], x, y)))
  296.         return;
  297.     ghost->msleep = 1;
  298.     Strcpy((char *)ghost->mextra, roguename());
  299.  
  300.     if (rn2(4)) {
  301.         ghostobj = mksobj_at(FOOD_RATION,x,y,FALSE);
  302.         ghostobj->quan = (long) rnd(7);
  303.         ghostobj->owt = weight(ghostobj);
  304.     }
  305.     if (rn2(2)) {
  306.         ghostobj = mksobj_at(MACE,x,y,FALSE);
  307.         ghostobj->spe = rnd(3);
  308.         if (rn2(4)) curse(ghostobj);
  309.     } else {
  310.         ghostobj = mksobj_at(TWO_HANDED_SWORD,x,y,FALSE);
  311.         ghostobj->spe = rnd(5) - 2;
  312.         if (rn2(4)) curse(ghostobj);
  313.     }
  314.     ghostobj = mksobj_at(BOW,x,y,FALSE);
  315.     ghostobj->spe = 1;
  316.     if (rn2(4)) curse(ghostobj);
  317.  
  318.     ghostobj = mksobj_at(ARROW,x,y,FALSE);
  319.     ghostobj->spe = 0;
  320.     ghostobj->quan = (long) rn1(10,25);
  321.     ghostobj->owt = weight(ghostobj);
  322.     if (rn2(4)) curse(ghostobj);
  323.  
  324.     if (rn2(2)) {
  325.         ghostobj = mksobj_at(RING_MAIL,x,y,FALSE);
  326.         ghostobj->spe = rn2(3);
  327.         if (!rn2(3)) ghostobj->oerodeproof = TRUE;
  328.         if (rn2(4)) curse(ghostobj);
  329.     } else {
  330.         ghostobj = mksobj_at(PLATE_MAIL,x,y,FALSE);
  331.         ghostobj->spe = rnd(5) - 2;
  332.         if (!rn2(3)) ghostobj->oerodeproof = TRUE;
  333.         if (rn2(4)) curse(ghostobj);
  334.     }
  335.     if (rn2(2)) {
  336.         ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR,x,y,TRUE);
  337.         ghostobj->known = TRUE;
  338.     }
  339. }
  340. #endif /* REINCARNATION /**/
  341.  
  342. /*extralev.c*/
  343.